<template>
  <div class="text-message font-size-14 font-weight-400 line-height-140" :class="{ self, translating, out }">
    <span v-for="(word, i) in charecters" :key="i" :class="['word', `word-${i % 6}`, { space: word === ' ' }]">{{
      word
    }}</span>
  </div>
</template>

<script setup>
import GraphemeSplitter from 'grapheme-splitter'
import { ref, watch } from 'vue'

const splitter = new GraphemeSplitter()

const props = defineProps({
  text: { type: String, required: true },
  self: { type: Boolean, default: false },
  translating: { type: Boolean, default: false },
})

const out = ref(false)
const charecters = ref(typeof props.text === 'string' ? splitter.splitGraphemes(props.text) : [])
let timerId
let rafId1
let rafId2
watch(
  () => props.text,
  (n, o) => {
    if (typeof o === 'string' && typeof n === 'string') {
      clearTimeout(timerId)
      cancelAnimationFrame(rafId1)
      cancelAnimationFrame(rafId2)
      out.value = true
      timerId = setTimeout(() => {
        charecters.value = splitter.splitGraphemes(n)
        rafId1 = requestAnimationFrame(() => (rafId2 = requestAnimationFrame(() => (out.value = false))))
      }, 750)
    }
  },
)
</script>

<style lang="scss">
@keyframes snake {
  from,
  to {
    transform: translateY(0);
  }
  25% {
    transform: translateY(-0.125rem);
  }
  75% {
    transform: translateY(0.125rem);
  }
}

.text-message {
  width: fit-content;
  padding: 0.5rem 1rem;
  background: rgb(var(--v-theme-primary-gray));
  border-radius: 0.25rem 1rem 1rem;

  &.self {
    background: rgb(var(--v-theme-primary));
    border-radius: 1rem 0.25rem 1rem 1rem;
  }

  &.out {
    .word {
      opacity: 0.05;
      &.word-0,
      &.word-2,
      &.word-4 {
        transform: translateY(-0.25rem);
      }
      &.word-1,
      &.word-3,
      &.word-5 {
        transform: translateY(0.25rem);
      }
    }
  }
  .word {
    display: inline-block;
    transition: transform 0.75s, opacity 0.75s;
    &.space {
      display: inline;
    }
  }

  &.translating {
    .word {
      animation: snake 0.75s ease-in-out infinite;
      &.word-0 {
        animation-delay: 0s;
      }
      &.word-1 {
        animation-delay: -0.125s;
      }
      &.word-2 {
        animation-delay: -0.25s;
      }
      &.word-3 {
        animation-delay: -0.375s;
      }
      &.word-4 {
        animation-delay: -0.5s;
      }
      &.word-5 {
        animation-delay: -0.625s;
      }
    }
  }
}
</style>
